package com.security;

import jdk.nashorn.internal.parser.Token;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ClassName AdminApplication
 * @Description TODO
 * @Author wushaopei
 * @Date 2021/5/13 14:13
 * @Version 1.0
 */
@SpringBootApplication
@RestController
@Slf4j
@EnableZuulProxy
public class AdminApplication {

  private RestTemplate restTemplate = new RestTemplate();

  /**
   * @Description TODO 第一种认证模式  Resource owner password
   * @param credentials
   * @param request
   */
//  @PostMapping("/login")
//  public void login(@RequestBody Credentials credentials , HttpServletRequest request){
//
//    String oauthServiceUrl = "http://localhost:9070/token/oauth/token";
//
//    HttpHeaders headers = new HttpHeaders();
//    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 不是json请求
//    // 网关的appId，appSecret，需要在数据库oauth_client_details注册
//    headers.setBasicAuth("admin","123456");
//    // 封装token
//    MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
//    params.add("username",credentials.getUsername());
//    params.add("password",credentials.getPassword());
//    params.add("grant_type","password");
//    params.add("scope","read write");
//
//    HttpEntity<MultiValueMap<String,String>> entity = new HttpEntity<>(params,headers);
//    ResponseEntity<TokenInfo> response = restTemplate.exchange(oauthServiceUrl, HttpMethod.POST,entity,TokenInfo.class);
//    request.getSession().setAttribute("token",response.getBody());
//    log.info("token info: 用户 {}, token " + response.getBody().toString());
//  }

  /**
   * @Description TODO 第二种认证模式 Authorization code grant
   * @param code
   * @param state
   * @param request
   */
  @GetMapping("/oauth/callback")
  public void callback(@RequestParam String code, String state , HttpServletRequest request, HttpServletResponse response) throws IOException {

    log.info("state is : {}", state);

    //认证服务器验token地址 /oauth/check_token 是  spring .security.oauth2的验token端点
    String oauthServiceUrl = "http://localhost:9070/token/oauth/token";

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 不是json请求
    // 网关的appId，appSecret，需要在数据库oauth_client_details注册
    headers.setBasicAuth("admin","123456");
    // 封装token
    MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
    params.add("code",code); // 授权码
    params.add("grant_type","authorization_code"); //授权类型-授权码模式
    //认证服务器会对比数据库客户端信息的的redirect_uri和这里的是不是一致，不一致就报错
    params.add("redirect_uri","http://admin.imooc.com:9999/oauth/callback" );

    HttpEntity<MultiValueMap<String,String>> entity = new HttpEntity<>(params,headers);
    ResponseEntity<TokenInfo> token = restTemplate.exchange(oauthServiceUrl, HttpMethod.POST,entity,TokenInfo.class);
    // 第一种方式：基于session实现的SSO
    // access_token
//    request.getSession().setAttribute("token",token.getBody().init());
    // 第二种方式：基于token实现的SSO
    // access_token
    Cookie accessTokenCookie = new Cookie("imooc_access_token",token.getBody().getAccess_token());
    accessTokenCookie.setMaxAge(token.getBody().getExpires_in().intValue());
    accessTokenCookie.setDomain("imooc.com");
    accessTokenCookie.setPath("/");
    response.addCookie(accessTokenCookie);
    // refresh_token
    Cookie refreshTokenCookie = new Cookie("imooc_refresh_token",token.getBody().getRefresh_token());
    accessTokenCookie.setMaxAge(2592000);
    accessTokenCookie.setDomain("imooc.com");
    accessTokenCookie.setPath("/");
    response.addCookie(refreshTokenCookie);

    log.info("token info: 用户 {}, token " + token.getBody().toString());
    response.sendRedirect("/");
  }

  @GetMapping("/me")
  public TokenInfo me(HttpServletRequest request){
    TokenInfo info = (TokenInfo)request.getSession().getAttribute("token");
    return info;
  }

  @PostMapping("/logout")
  public void logout(HttpServletRequest request,HttpServletResponse response){
    request.getSession().invalidate();
  }

  public static void main(String[] args) {
    SpringApplication.run(AdminApplication.class, args);
  }
}
